package com.empire.module.member.service.user;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.*;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.empire.framework.common.encrypt.EncryptRequest;
import com.empire.framework.common.encrypt.EncryptResponse;
import com.empire.framework.common.enums.ManageTypeEnum;
import com.empire.framework.common.pojo.PageResult;
import com.empire.framework.security.core.LoginUser;
import com.empire.framework.security.core.service.MockCryptoUtil;
import com.empire.framework.security.core.service.PkiVerifyApiClient;
import com.empire.framework.security.core.util.SecurityFrameworkUtils;
import com.empire.module.member.controller.admin.user.vo.*;
import com.empire.module.member.convert.user.MemberUserConvert;
import com.empire.module.member.dal.dataobject.group.MemberGroupDO;
import com.empire.module.member.dal.dataobject.user.MemberUserDO;
import com.empire.module.member.dal.mysql.group.MemberGroupMapper;
import com.empire.module.member.dal.mysql.user.MemberUserMapper;
import com.empire.module.member.service.dept.DeptMemberService;
import com.empire.module.member.service.miping.MiPingService;
import com.empire.module.system.api.dept.DeptApi;
import com.empire.module.system.api.dept.dto.DeptRespDTO;
import com.google.common.annotations.VisibleForTesting;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

import static com.empire.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.empire.framework.common.exception.util.ServiceExceptionUtil.exceptionWithMsg;
import static com.empire.module.member.enums.ErrorCodeConstants.*;
import static com.empire.module.system.enums.ErrorCodeConstants.USER_IMPORT_LIST_IS_EMPTY;

/**
 * 会员 User Service 实现类
 *
 * @author 未来源码
 */
@Service
@Valid
@Slf4j
public class MemberUserServiceImpl extends ServiceImpl<MemberUserMapper, MemberUserDO> implements MemberUserService {

    @Resource
    private MemberUserMapper memberUserMapper;

    @Resource
    private DeptMemberService deptMemberService;
    
    @Resource
    private MemberGroupMapper memberGroupMapper;

    @Resource
    private DeptApi deptApi;

    @Resource
    private MiPingService miPingService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createUser(MemberUserSaveReqVO createReqVO) {
        //验证身份证、护照号是否已经存在
        validateUserIdCardOrPassportNumberExists(createReqVO.getIdcard(),
                createReqVO.getPassportNumber(), createReqVO.getForeigner());
        // 创建
        MemberUserDO createObj = MemberUserConvert.INSTANCE.convert(createReqVO);

        memberUserMapper.insert(createObj);
        return createObj.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateUser(MemberUserUpdateReqVO updateReqVO) {
        // 校验存在
        validateUserExists(updateReqVO.getId());

        // 更新
        MemberUserDO updateObj = MemberUserConvert.INSTANCE.convert(updateReqVO);

        memberUserMapper.updateById(updateObj);
    }

    @Override
    public MemberUserDO getUser(Long id) {
        return memberUserMapper.selectById(id);
    }

    @Override
    public MemberUserDO getByIdCard(String idcard) {

        MemberUserDO memberUserDO = memberUserMapper.selectByIdcard(idcard);
        if (memberUserDO == null) {
            memberUserDO = memberUserMapper.selectByPassportNumber(idcard);
        }
        return memberUserDO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void bindDeptMember(DeptMemberUserUpdateReqVO updateReqVO) {
        // 清空上次绑定
        deptMemberService.deleteListByMemberId(updateReqVO.getId());
        // 部门绑定
        if (updateReqVO.getDeptId() != null) {
            if (StrUtil.isNotEmpty(updateReqVO.getDeptName())) {
                MemberUserDO memberUserDO = memberUserMapper.selectById(updateReqVO.getId());
                memberUserDO.setDeptId(updateReqVO.getDeptId());
                memberUserDO.setDeptName(updateReqVO.getDeptName());
                memberUserMapper.updateById(memberUserDO);
            }
        }
    }

    @VisibleForTesting
    void validateUserExists(Long id) {
        if (id == null) {
            return;
        }
        MemberUserDO user = memberUserMapper.selectById(id);
        if (user == null) {
            throw exception(USER_NOT_EXISTS);
        }
    }

    /**
     * 验证身份证是否已经存在
     *
     * @param idcard    身份证号
     * @param number    护照号
     * @param foreigner 是否外国人
     */
    @VisibleForTesting
    void validateUserIdCardOrPassportNumberExists(String idcard, String number, Integer foreigner) {
        if (foreigner == null || StrUtil.isBlank(number)) {
            return;
        }
        MemberUserDO user = null;
        if (foreigner == 1) {
            user = memberUserMapper.selectByPassportNumber(number);
        }
        if (foreigner == 2) {
            user = memberUserMapper.selectByIdcard(idcard);
        }
        if (user != null) {
            if (foreigner == 1) {
                throw exceptionWithMsg(USER_PASSPORT_NUMBER_EXIST, "目前管控单位是：" + user.getDeptName());
            }
            throw exceptionWithMsg(USER_IDCARD_EXIST, "目前管控单位是：" + user.getDeptName());
        }
    }

    @Override
    public PageResult<MemberUserDO> getUserPage(MemberUserPageReqVO pageReqVO) {
        PageResult<MemberUserDO> result;
        if (pageReqVO.getGroupId() != null) {
            pageReqVO.setGroupIdList(Collections.singletonList(pageReqVO.getGroupId()));
        }
        //过滤登陆用户数据
        filterLoginUser(pageReqVO);
        result = memberUserMapper.selectPage(pageReqVO);
        return result;
    }

    @Override
    public PageResult<MemberUserDO> getUserCurInfoPage(MemberUserPageReqVO pageReqVO) {
        //过滤登陆用户数据
        filterLoginUser(pageReqVO);
        return memberUserMapper.selectCurInfoPage(pageReqVO);
    }

    @Override
    public List<Long> getMyUserIdList() {
        LoginUser user = SecurityFrameworkUtils.getLoginUser();
        LambdaQueryWrapper<MemberUserDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.select(MemberUserDO::getId);
        if (user != null) {
            Map<String, String> info = user.getInfo();
            // 用户管理级别
            String manageType = info.get(LoginUser.INFO_MANAGER_TYPE);
            // 用户部门
            String deptId = info.get(LoginUser.INFO_KEY_DEPT_ID);
            // 人员分类
            String category = info.get(LoginUser.DEPT_MANAGER_CATEGORY);
            if (manageType.equals(ManageTypeEnum.CITY.getValue() + "")) {
                // 2-市级大队，只能看部门分配的人员分类 category
                List<String> groupIds = Arrays.asList(category.split(StrUtil.COMMA));
                List<Long> groupIdList = groupIds.stream().map(Long::parseLong).toList();
                if (groupIdList.size() == 1) {
                    queryWrapper.eq(MemberUserDO::getGroupId, groupIdList.getFirst());
                } else {
                    queryWrapper.in(MemberUserDO::getGroupId, groupIdList);
                }
            }
            if (manageType.equals(ManageTypeEnum.AREA.getValue() + "")) {
                // 3-区县大队，只能看自己作为管控单位的对应deptId的人员
                queryWrapper.eq(MemberUserDO::getDeptId, deptId);
            }
        }
        // 查询并提取id列表
        List<MemberUserDO> userList = memberUserMapper.selectList(queryWrapper);
        return userList.stream()
                .map(MemberUserDO::getId)
                .collect(Collectors.toList());
    }

    /**
     * 过滤登陆用户数据
     *
     * @param pageReqVO 查询参数
     */
    private static void filterLoginUser(MemberUserPageReqVO pageReqVO) {
        LoginUser user = SecurityFrameworkUtils.getLoginUser();
        if (user != null) {
            Map<String, String> info = user.getInfo();
            // 用户管理级别
            String manageType = info.get(LoginUser.INFO_MANAGER_TYPE);
            // 用户部门
            String deptId = info.get(LoginUser.INFO_KEY_DEPT_ID);
            // 人员分类
            String category = info.get(LoginUser.DEPT_MANAGER_CATEGORY);
            if (manageType.equals(ManageTypeEnum.CITY.getValue() + "")) {
                // 2-市级大队，只能看部门分配的人员分类 category
                if (pageReqVO.getGroupId() != null && category != null && category.contains(",")) {
                    List<String> groupIds = Arrays.asList(category.split(StrUtil.COMMA));
                    List<Long> groupIdList = groupIds.stream()
                            .map(Long::parseLong)
                            .toList();
                    if (groupIdList.size() == 1) {
                        pageReqVO.setGroupId(groupIdList.getFirst());
                    } else {
                        pageReqVO.setGroupIdList(groupIdList);
                    }
                }
            }
            if (manageType.equals(ManageTypeEnum.AREA.getValue() + "")) {
                // 3-区县大队，只能看自己作为管控单位的对应deptId的人员
                pageReqVO.setDeptId(Long.parseLong(deptId));
            }
        }
    }

    @Override
    public Long getUserCountByGroupId(Long groupId) {
        return memberUserMapper.selectCountByGroupId(groupId);
    }

    @Override
    public Long getUserCountByTagId(Long tagId) {
        return memberUserMapper.selectCountByTagId(tagId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public MemberImportRespVO importUserList(List<MemberImportExcelVO> importUsers, boolean isUpdateSupport) {
        // 1. 参数校验
        if (CollUtil.isEmpty(importUsers)) {
            throw exception(USER_IMPORT_LIST_IS_EMPTY);
        }

        // 2. 初始化结果容器
        Set<String> successIds = new HashSet<>();
        Set<String> failureIds = new HashSet<>();
        Map<String, String> failureReasons = new LinkedHashMap<>();

        // 3. 遍历处理每个导入用户
        for (MemberImportExcelVO importUser : importUsers) {
            processImportUser(importUser, successIds, failureIds, failureReasons);
        }

        // 4. 构建并返回结果
        return MemberImportRespVO.builder()
                .createIdcardList(new ArrayList<>(successIds))
                .updateIdcardList(new ArrayList<>())
                .failureIdcardMap(failureReasons)
                .build();
    }

    /**
     * 处理单个导入用户
     */
    private void processImportUser(MemberImportExcelVO importUser,
                                   Set<String> successIds,
                                   Set<String> failureIds,
                                   Map<String, String> failureReasons) {
        try {
            Integer foreigner = importUser.getForeigner();
            String uniqueId = getUniqueId(importUser, foreigner); // 获取唯一标识（身份证/护照号）

            // 校验证件号必填性
            String idCardError = checkIdCardRequired(importUser, foreigner);
            if (idCardError != null) {
                addFailure(failureIds, failureReasons, uniqueId, idCardError);
                return;
            }

            // 校验必填字段
            String requiredError = checkRequiredFields(importUser, foreigner);
            if (requiredError != null) {
                addFailure(failureIds, failureReasons, uniqueId, requiredError);
                return;
            }

            // 检查用户是否已存在
            MemberUserDO existingUser = getExistingUser(importUser, foreigner);
            if (existingUser != null) {
                handleExistingUser(foreigner, uniqueId, successIds, failureReasons);
                return;
            }

            // 新增用户
            createNewUser(importUser);
            successIds.add(uniqueId);

        } catch (Exception e) {
            String uniqueId = StrUtil.isEmpty(importUser.getIdcard()) ? importUser.getPassportNumber() : importUser.getIdcard();
            if (importUser.getForeigner() != null) {
                uniqueId = getUniqueId(importUser, importUser.getForeigner());
            }
            addFailure(failureIds, failureReasons, uniqueId, "导入失败：" + e.getMessage());
            log.error("导入用户异常", e); // 建议用日志框架替代printStackTrace
        }
    }

    /**
     * 获取用户唯一标识（身份证号或护照号）
     */
    private String getUniqueId(MemberImportExcelVO user, Integer foreigner) {
        return foreigner == 1 ? user.getPassportNumber() : user.getIdcard();
    }

    /**
     * 校验证件号必填性
     */
    private String checkIdCardRequired(MemberImportExcelVO user, Integer foreigner) {
        if (foreigner == 1 && StrUtil.isEmpty(user.getPassportNumber())) {
            return "境外人员，护照号不能为空";
        }
        if (foreigner == 2 && StrUtil.isEmpty(user.getIdcard())) {
            return "国内人员，身份证号不能为空";
        }
        return null;
    }

    /**
     * 校验必填字段
     */
    private String checkRequiredFields(MemberImportExcelVO user, Integer foreigner) {
        if (foreigner == null
                || user.getSex() == null
                || StrUtil.isEmpty(user.getName())
                || StrUtil.isEmpty(user.getGroupName())
                || StrUtil.isEmpty(user.getDeptName())
                || StrUtil.isEmpty(user.getLiveAddress())
                || StrUtil.isEmpty(user.getBirthPlace())) {
            return "带星号必填列未补充完整";
        }
        return null;
    }

    /**
     * 查询已存在的用户
     */
    private MemberUserDO getExistingUser(MemberImportExcelVO user, Integer foreigner) {
        return foreigner == 1
                ? memberUserMapper.selectByPassportNumber(user.getPassportNumber())
                : memberUserMapper.selectByIdcard(user.getIdcard());
    }

    /**
     * 处理已存在的用户
     */
    private void handleExistingUser(Integer foreigner, String uniqueId,
                                    Set<String> successIds, Map<String, String> failureReasons) {
        if (foreigner == 1) {
            successIds.add(uniqueId);
            failureReasons.put(uniqueId, "该外国人护照号已存在");
        } else {
            failureReasons.put(uniqueId, "该身份证号码已存在");
        }
    }

    /**
     * 创建新用户
     */
    private void createNewUser(MemberImportExcelVO importUser) {
        MemberUserDO createObj = new MemberUserDO();
        BeanUtil.copyProperties(importUser, createObj);
        // 设置人员分类（原代码未完成，此处保留结构）
        MemberGroupDO group = memberGroupMapper.selectOne("name", importUser.getGroupName());
        if (group != null) {
            createObj.setGroupId(group.getId());
        }
        DeptRespDTO dept = deptApi.getDeptByName(importUser.getDeptName());
        if (dept != null) {
            createObj.setDeptId(dept.getId());
        }
        memberUserMapper.insert(createObj);
    }

    /**
     * 添加失败记录
     */
    private void addFailure(Set<String> failureIds, Map<String, String> reasons, String id, String reason) {
        failureIds.add(id);
        reasons.put(id, reason);
    }

    @Override
    public Boolean deleteUser(Long id) {
        boolean suc = memberUserMapper.deleteById(id) > 0;
        if (suc) {
            //TODO 删除预警条件
        }
        return suc;
    }

}
